package com.joinway.framework.extension.net.http;

import java.io.File;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;

import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.ssl.TrustStrategy;

public class RestSSLHttpClient extends RestHttpClient implements HostnameVerifier {

	public RestSSLHttpClient(){
		try{
			SSLContextBuilder builder = new SSLContextBuilder();
			builder.loadTrustMaterial(null, new TrustStrategy(){
				@Override
				public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
					return true;
				}
			});
			
			SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(builder.build(), this);
					
			Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder
			        .<ConnectionSocketFactory> create()
			        .register("https", factory)
			        .build();
			
			PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
			
			client = HttpClients.custom().setConnectionManager(cm).build();
		}catch(Exception e){
			throw new RuntimeException("failed to create ssl http client", e);
		}		
	}
	
	public RestSSLHttpClient(String keyStore){
		this(keyStore, null);
	}
	
	public RestSSLHttpClient(String keyStore, String password){
		try{
			 SSLContext sslcontext;
			 
			 if(password == null || password.trim().length() == 0){
				 sslcontext = SSLContexts.custom()
				            .loadTrustMaterial(new File(keyStore))
				            .build();				 
			 }else{
				 sslcontext = SSLContexts.custom()
			            .loadTrustMaterial(new File(keyStore), password.toCharArray(), new TrustSelfSignedStrategy())
			            .build();
			 }
			 
			 SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(
				sslcontext,
				new String[] { "TLSv1" },
				null,
				this
		     );
			 
			 client = HttpClients.custom().setSSLSocketFactory(factory).build();
		}catch(Exception e){
			throw new RuntimeException("failed to create ssl http client", e);
		}
	}

	@Override
	public boolean verify(String hostname, SSLSession session) {
		return true;
	}
}
